﻿using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using Furion.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.ValueGeneration;
using YShop.Core;

namespace YShop.EntityFramework.Core
{
    [AppDbContext("DatabaseSettings:ConnectionString")]
    public class DefaultDbContext : AppDbContext<DefaultDbContext>, IModelBuilderFilter
    {
        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)
        {
            EnabledEntityChangedListener = true;
        }

        #region 全局过滤
        public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)
        {
            var expression = BuilderIsDeleteLambdaExpression(entityBuilder);
            if (expression == null) return;

            entityBuilder.HasQueryFilter(expression);
            entityBuilder
                .Property("Id")
                .ValueGeneratedOnAdd()
                .HasValueGenerator<PrimaryKeyIncrementGenerator>();

        }

        /// <summary>
        /// 构建 u => EF.Property<bool>(u, "IsDeleted") == false 表达式
        /// </summary>
        /// <param name="entityBuilder"></param>
        /// <returns></returns>
        private LambdaExpression BuilderIsDeleteLambdaExpression(EntityTypeBuilder entityBuilder)
        {
            // 获取实体构建器元数据
            var metadata = entityBuilder.Metadata;
            if (metadata.FindProperty(nameof(Entity.IsDeleted)) == null) return default;

            // 创建表达式元素
            var parameter = Expression.Parameter(metadata.ClrType, "u");
            var properyName = Expression.Constant(nameof(Entity.IsDeleted));
            var propertyValue = Expression.Constant(false);

            // 构建表达式 u => EF.Property<bool>(u, "IsDeleted") == false
            var expressionBody = Expression.Equal(Expression.Call(typeof(EF), nameof(EF.Property), new[] { typeof(bool) }, parameter, properyName), propertyValue);
            var expression = Expression.Lambda(expressionBody, parameter);

            return expression;
        }

        /// <summary>
        /// 提交之前
        /// </summary>
        /// <param name="eventData"></param>
        /// <param name="result"></param>
        protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result)
        {
            eventData.Context.ChangeTracker
                .Entries()
                .Where(e => e.Entity is BaseEntity)
                .ToList()
                .ForEach(e =>
                {
                    //添加操作
                    if (e.State == EntityState.Added)
                    {
                        if (e.Entity is ICreateAduitEntity)
                        {
                            var entity = e.Entity as ICreateAduitEntity;
                            entity.CreateTime = DateTime.Now;
                            entity.CreateUserId = null;
                        }
                        if (e.Entity is IDeleteAduitEntity)
                        {
                            var entity = e.Entity as IDeleteAduitEntity;
                            entity.IsDeleted = false;
                        }
                    }
                    //修改操作
                    if (e.State == EntityState.Modified)
                    {
                        //if (e.Entity is IDeleteAduitEntity)
                        //{
                        //    var entity = e.Entity as IDeleteAduitEntity;
                        //    if (entity.IsDeleted)
                        //    {
                        //        entity.DeleteTime = DateTime.Now;
                        //        entity.DeleteUserId = null;
                        //    }
                        //}

                        //if (e.Entity is IUpdateAuditEntity)
                        //{
                        //    var entity = e.Entity as IUpdateAuditEntity;
                        //    entity.UpdateTime = DateTime.Now;
                        //    entity.UpdateUserId = null;
                        //}
                    }
                });

        }
        #endregion

        #region Id生成器

        public class PrimaryKeyIncrementGenerator : ValueGenerator<string>
        {
            public override bool GeneratesTemporaryValues => false;

            public override string Next([NotNullAttribute] EntityEntry entry)
            {
                return Utils.NewGuid();
            }

        }
        #endregion
    }
}